// const defaultOption = {
// 	duration: 300,
// 	timingFunction: 'linear',
// 	delay: 0,
// 	transformOrigin: '50% 50% 0'
// }
// #ifdef APP-NVUE
const nvueAnimation = uni.requireNativePlugin('animation');
// #endif
class MPAnimation {
	constructor(options, _this) {
		this.options = options;
		this.animation = uni.createAnimation(options);
		this.currentStepAnimates = {};
		this.next = 0;
		this.$ = _this;
	}

	_nvuePushAnimates(type, args) {
		let aniObj = this.currentStepAnimates[this.next];
		let styles = {};
		if (!aniObj) {
			styles = {
				styles: {},
				config: {},
			};
		} else {
			styles = aniObj;
		}
		if (animateTypes1.includes(type)) {
			if (!styles.styles.transform) {
				styles.styles.transform = '';
			}
			let unit = '';
			if (type === 'rotate') {
				unit = 'deg';
			}
			styles.styles.transform += `${type}(${args + unit}) `;
		} else {
			styles.styles[type] = `${args}`;
		}
		this.currentStepAnimates[this.next] = styles;
	}
	_animateRun(styles = {}, config = {}) {
		let ref = this.$.$refs['ani'].ref;
		if (!ref) return;
		return new Promise((resolve, reject) => {
			nvueAnimation.transition(
				ref,
				{
					styles,
					...config,
				},
				(res) => {
					resolve();
				}
			);
		});
	}

	_nvueNextAnimate(animates, step = 0, fn) {
		let obj = animates[step];
		if (obj) {
			let { styles, config } = obj;
			this._animateRun(styles, config).then(() => {
				step += 1;
				this._nvueNextAnimate(animates, step, fn);
			});
		} else {
			this.currentStepAnimates = {};
			typeof fn === 'function' && fn();
			this.isEnd = true;
		}
	}

	step(config = {}) {
		// #ifndef APP-NVUE
		this.animation.step(config);
		// #endif
		// #ifdef APP-NVUE
		this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config);
		this.currentStepAnimates[this.next].styles.transformOrigin =
			this.currentStepAnimates[this.next].config.transformOrigin;
		this.next++;
		// #endif
		return this;
	}

	run(fn) {
		// #ifndef APP-NVUE
		this.$.animationData = this.animation.export();
		this.$.timer = setTimeout(() => {
			typeof fn === 'function' && fn();
		}, this.$.durationTime);
		// #endif
		// #ifdef APP-NVUE
		this.isEnd = false;
		let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref;
		if (!ref) return;
		this._nvueNextAnimate(this.currentStepAnimates, 0, fn);
		this.next = 0;
		// #endif
	}
}

const animateTypes1 = [
	'matrix',
	'matrix3d',
	'rotate',
	'rotate3d',
	'rotateX',
	'rotateY',
	'rotateZ',
	'scale',
	'scale3d',
	'scaleX',
	'scaleY',
	'scaleZ',
	'skew',
	'skewX',
	'skewY',
	'translate',
	'translate3d',
	'translateX',
	'translateY',
	'translateZ',
];
const animateTypes2 = ['opacity', 'backgroundColor'];
const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom'];
animateTypes1.concat(animateTypes2, animateTypes3).forEach((type) => {
	MPAnimation.prototype[type] = function (...args) {
		// #ifndef APP-NVUE
		this.animation[type](...args);
		// #endif
		// #ifdef APP-NVUE
		this._nvuePushAnimates(type, args);
		// #endif
		return this;
	};
});

export function createAnimation(option, _this) {
	if (!_this) return;
	clearTimeout(_this.timer);
	return new MPAnimation(option, _this);
}
